#include <SmrtQuery.h>
#include "FunTrace.h"
#include <aknglobalnote.h>
#include <e32math.h>
#include <eikimage.h>
#include <akndialog.h>
#include <aknquerycontrol.h>
#include <aknnumedwin.h>
#include <es_sock.h>
#include <escapeutils.h>
#include <ezgzip.h>
#include <SingaporeBus.rsg>
#include <aknquerydialog.h>
#include <eikapp.h>


const TInt DndTimedOut = -5120;
const TInt kSmrtTimeout = 45*1000000;
const TInt kCrowdSmrtTimeout = 10*1000000;

#define EAknEditorFlagEnablePartialScreen             0x200000

#include <ImageConversion.h>
#include <euserhl.h>
#include "Binder.h"


static void PrintNoteL(TRefByValue<const TDesC> aFormat, ...)
    {
    VA_LIST list;
    VA_START(list, aFormat);
    TBuf<256> buf;
    buf.FormatList(aFormat, list);
    VA_END(list);
	CAknGlobalNote* globalNote = CAknGlobalNote::NewLC();
	globalNote->ShowNoteL(EAknGlobalInformationNote, buf); 
    CleanupStack::PopAndDestroy(globalNote);
    }


static TBool IsSpace(TChar ch)
	{
	switch(ch)
		{
		case ' ': case '\n': case '\t': case '\r':
			return ETrue;
			break;
		default:
			return EFalse;
		}
	}

static TPtrC8 IrisTrim( const TDesC8& aBuf)
	{
	TInt beg, end;
	for(beg = 0 ; beg < aBuf.Length() && IsSpace( aBuf[beg] ) ; ++beg);
	if(beg == aBuf.Length()) return aBuf.Mid(0, 0);
	for(end = aBuf.Length() - 1 ; end > beg && IsSpace( aBuf[end] ) ; --end);
	return aBuf.Mid(beg, end + 1 - beg);
	}


static TPtrC8 IrisExtractField(const TDesC8& aPrefix, const TDesC8& aSuffix, TPtrC8& aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	TPtrC8 ret;
	TInt begfield = aBuf.Find(aPrefix);
	if(begfield != KErrNotFound)
		{
		TInt endfield = aBuf.Mid(begfield + aPrefix.Length()).Find(aSuffix);
		if(endfield != KErrNotFound)
			{
			ret.Set( aBuf.Mid(begfield + aPrefix.Length(), endfield) );
			aBuf.Set( aBuf.Mid( begfield + aPrefix.Length() + endfield + aSuffix.Length() ) );
			return ret;
			}
		}
	aBuf.Set( aBuf.Mid( aBuf.Length() ) );
	return ret;
	}


_LIT(kFormatRequestPending, "\trequesting...");
_LIT(kFormatRequestScheduled, "\tqueued, select to request");
_LIT(kFormatRequestScheduledWaitingConnection, "\tqueued, waiting connection");
_LIT(kFormatRequestWait, "\tselect to request");
_LIT(kFormatRequestSchedule, "\tevery %S");
_LIT(kFormatRequestCompleted, "\t%S \xf814 %S");
_LIT(kFormatRequestBlocked, "\tunexpected answer (probably blocked by SBS or SMRT), please check whether the app has been updated");
_LIT(kFormatRequestPendingCaptcha, "\trequesting captcha...");
_LIT(kFormatRequestDownloadingCaptcha, "\tdownloading captcha...");
_LIT(kFormatCaptchaError, "\tcaptcha processing error");
_LIT(kFormatRequestSubmittingCaptcha, "\tsubmitting captcha...");
_LIT(kFormatSolvingCaptcha, "\tsolving captcha...");
_LIT(kFormatRequestError, "\terror (%S, %S)");
_LIT(kFormatRequestUnavailable, "\tschedule unavailable");
_LIT(kFormatRequestPendingInitialization, "\twaiting for initialization...");
_LIT(kFormatRequestPendingToken, "\trequesting token...");
_LIT(kFormatRequestPendingCrowdToken, "\trequesting crowd token...");
_LIT(kFormatRequestSelectingBus, "\tselecting bus...");



/**
 * First phase of Symbian two-phase construction. Should not contain any
 * code that could leave.
 */
CSmrtSession::CSmrtSession()
	{
	iSmrtTimeoutTimer.CreateLocal();
	iSmrtConnectTimeoutTimer.CreateLocal();
	iCrowdSmrtTimeoutTimer.CreateLocal();

	iSmrtTimeoutTimerHelper = NULL;
	iCrowdSmrtTimeoutTimerHelper = NULL;
	
	iSmrtSessionCookie = NULL;
	iSmrtEventValidation = NULL;
	iSmrtViewState = NULL;
	
	iSmrtCaptchaDialog = NULL;
	}

/** 
 * The view's destructor removes the container from the control
 * stack and destroys it.
 */
CSmrtSession::~CSmrtSession()
	{
	
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	delete iSmrtSessionCookie;
	
	delete iSmrtTimeoutTimerHelper;
	delete iCrowdSmrtTimeoutTimerHelper;
	delete iSmrtEventValidation;
	delete iSmrtViewState;
	iSmrtTimeoutTimer.Close();
	iSmrtConnectTimeoutTimer.Close();
	iCrowdSmrtTimeoutTimer.Close();
	
	iSmrtSessionTransaction.Close();
	iCrowdSmrtSessionTransaction.Close();
	iSmrtCaptchaTransaction.Close();
	iSmrtSolveCaptchaTransaction.Close();
	iCrowdSmrtSessionUpdateTransaction.Close();
	iSmrtSelectBusTransaction.Close();
	for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
		delete iSmrtQueries[i];
	iSmrtQueries.Close();
	iHTTPSession.Close();
	}

CSmrtSession* CSmrtSession::NewL()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	CSmrtSession* self = CSmrtSession::NewLC();
	CleanupStack::Pop( self );
	return self;
	}

CSmrtSession* CSmrtSession::NewLC()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	CSmrtSession* self = new ( ELeave ) CSmrtSession();
	CleanupStack::PushL( self );
	self->ConstructL();
	return self;
	}



void CSmrtSession::NotifyConnected()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
		if(iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestError)
			SubmitL(iSmrtQueries[i]);
	}

void CSmrtSession::CloseConnectionL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	CancelAllSmrtRequestsL();
	for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
		if( (iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending || iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPendingInitialization))
			{
			_LIT8 (connectionClosed, "connection closed");
			iSmrtQueries[i]->iRequestStatus = CSmrtQuery::ERequestError;
			(*iSmrtQueries[i]->iCallback.Get())(iSmrtQueries[i], (*iSmrtQueries[i]->iStationNumber), (*iSmrtQueries[i]->iServiceName), CSmrtQuery::ERequestError, (*&kFormatRequestError()), (*&connectionClosed), (*&connectionClosed));
			}
	iHTTPSession.Close();
	}

void CSmrtSession::SetConnectionInfoL(const RConnection& aConnection, const RSocketServ& aSocketServ)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iHTTPSession.OpenL();
	RStringPool strP = iHTTPSession.StringPool();
	RHTTPConnectionInfo connInfo = iHTTPSession.ConnectionInfo();
	connInfo.SetPropertyL ( strP.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable() ), THTTPHdrVal (aSocketServ.Handle()) );
	TInt connPtr = REINTERPRET_CAST(TInt, &aConnection);
	connInfo.SetPropertyL ( strP.StringF(HTTP::EHttpSocketConnection, RHTTPSession::GetTable() ), THTTPHdrVal (connPtr) );
	RHTTPSessionSetHeaderL(iHTTPSession, HTTP::EUserAgent,
#include "smrt_query_user_agent.txt"
			);
	}


void CSmrtSession::ConstructL()
	{
TFunTrace funTrace(__PRETTY_FUNCTION__);

	iSmrtTimeoutTimerHelper = CActiveHelper<RTimer*>::NewL();
	iCrowdSmrtTimeoutTimerHelper = CActiveHelper<RTimer*>::NewL();

	iSmrtInitalizationCycle = EFalse;
	iSmrtSessionTransactionTarget = CHTTPTransactionTarget::NewL();
	iSmrtCaptchaTransactionTarget = CHTTPTransactionTarget::NewL();
	iSmrtSolveCaptchaTransactionTarget = CHTTPTransactionTarget::NewL();
	iSmrtCaptchaTransactionSource = new (ELeave) CHTTPTransactionSource;

	iSmrtSelectBusTransactionTarget = CHTTPTransactionTarget::NewL();
	iSmrtSelectBusTransactionSource = new (ELeave) CHTTPTransactionSource;
	
	iCrowdSmrtSessionTransactionTarget = CHTTPTransactionTarget::NewL();

	iCrowdSmrtSessionUpdateTransactionTarget = CHTTPTransactionTarget::NewL();
	iCrowdSmrtSessionUpdateTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedCrowdSmrtSessionUpdateAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
	iCrowdSmrtSessionUpdateTransactionSource = new (ELeave) CHTTPTransactionSource;

	
	iDeflateDecompressor = CDeflateDecompressor::NewL();
	
	iCrowdSmrtSession = EFalse;
	
	iLastFailureSmrtConnect = Time::MinTTime();
	iLastFailureCrowdSmrtSession = Time::MinTTime();

	TTime now;
	now.UniversalTime();
	TInt64 iSeed = now.Int64();
	iCrowdSmrtSessionId = Math::Rand(iSeed) % 100;
	}


void CSmrtSession::SubmitL(CSmrtQuery* aQuery)
{
TFunTrace funTrace(__PRETTY_FUNCTION__);

	TTime currentTime;
	currentTime.HomeTime();
	TTimeIntervalSeconds secondsFromLastFailureIrisApi, secondsFromLastFailureCrowdSmrtSession;
	
	if( (aQuery->iServiceName->Locate('R') != KErrNotFound || aQuery->iServiceName->Locate('C') != KErrNotFound) )
		{
		aQuery->iRequestStatus = CSmrtQuery::ERequestUnavailable;
		(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestUnavailable, (*&kFormatRequestUnavailable()), (*&KNullDesC8()), (*&KNullDesC8()));
		}
	else if(currentTime.SecondsFrom(iLastFailureSmrtConnect, secondsFromLastFailureIrisApi) == KErrOverflow ||
			secondsFromLastFailureIrisApi >= TTimeIntervalSeconds(30)
		)
		{
		TInt i;
		for(i = 0 ;
			i < iSmrtQueries.Count() &&
			(
			iSmrtQueries[i]->iTransactionType != CSmrtQuery::ESmrtConnect ||
			iSmrtQueries[i]->iServiceTransaction == RHTTPTransaction() ||
			iSmrtQueries[i]->iRequestStatus != CSmrtQuery::ERequestPending ||
			*iSmrtQueries[i]->iStationNumber != *aQuery->iStationNumber)
			; ++i);
		if(i < iSmrtQueries.Count())
			{
			// we already have a pending query taking care of this bus stop
			aQuery->iRequestStatus = CSmrtQuery::ERequestPending;
			aQuery->iTransactionType = CSmrtQuery::ESmrtConnect;
			(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestPending, (*&kFormatRequestPendingInitialization()), (*&KNullDesC8()), (*&KNullDesC8()));
			}
		else
			SubmitSmrtConnectRequestL(aQuery);
		}
	else if(iSmrtInitalizationCycle)
		{
		aQuery->iTransactionType = CSmrtQuery::ESmrtArrivalTime;
		aQuery->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
		(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatRequestPendingInitialization()), (*&KNullDesC8()), (*&KNullDesC8()));
		}
	else if(iSmrtSessionCookie == NULL)
		{
		iSmrtInitalizationCycle = ETrue;
		iSmrtInitializationPilotService = aQuery;
		aQuery->iTransactionType = CSmrtQuery::ESmrtArrivalTime;
		
		if(currentTime.SecondsFrom(iLastFailureCrowdSmrtSession, secondsFromLastFailureCrowdSmrtSession) == KErrOverflow ||
				secondsFromLastFailureCrowdSmrtSession >= TTimeIntervalSeconds(30)
			)
			SubmitCrowdSmrtSessionRequestL(); // we try the crowd session first
		else
			SubmitSmrtSessionCookieRequestL();
		}
	else
		{
		SubmitSmrtBusArrivalSearchNoHeaderRequestL(aQuery);
		}
}


void CSmrtSession::Cancel(CSmrtQuery* aQuery)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(aQuery->iServiceTransaction != RHTTPTransaction())
		{
		const TDesC8& path = aQuery->iServiceTransaction.Request().URI().Extract(EUriPath);
		if(aQuery->iTransactionType == CSmrtQuery::ESmrtConnect)
			SmrtConnectTransactionError(aQuery, KErrCancel, RHTTPTransaction());
		}
	if(iSmrtInitalizationCycle && aQuery == iSmrtInitializationPilotService)
		{
		SmrtTransactionError(aQuery, KErrCancel, RHTTPTransaction());
		if(iSmrtCaptchaDecoderTarget.Get()) iSmrtCaptchaDecoderTarget->Cancel();
		if(iSmrtCaptchaBitmapScalerTarget.Get()) iSmrtCaptchaBitmapScalerTarget->Cancel();
		if(iSmrtSessionTransaction != RHTTPTransaction())
			{
			iSmrtSessionTransaction.Cancel();
			iSmrtSessionTransaction.Close();
			iSmrtSessionTransaction = RHTTPTransaction();
			}
		if(iCrowdSmrtSessionTransaction != RHTTPTransaction())
			{
			iCrowdSmrtSessionTransaction.Cancel();
			iCrowdSmrtSessionTransaction.Close();
			iCrowdSmrtSessionTransaction = RHTTPTransaction();
			}
		if(iCrowdSmrtSessionUpdateTransaction != RHTTPTransaction())
			{
			iCrowdSmrtSessionUpdateTransaction.Cancel();
			iCrowdSmrtSessionUpdateTransaction.Close();
			iCrowdSmrtSessionUpdateTransaction = RHTTPTransaction();
			}
		if(iSmrtCaptchaTransaction != RHTTPTransaction())
			{
			iSmrtCaptchaTransaction.Cancel();
			iSmrtCaptchaTransaction.Close();
			iSmrtCaptchaTransaction = RHTTPTransaction();
			}
		if(iSmrtSolveCaptchaTransaction != RHTTPTransaction())
			{
			iSmrtSolveCaptchaTransaction.Cancel();
			iSmrtSolveCaptchaTransaction.Close();
			iSmrtSolveCaptchaTransaction = RHTTPTransaction();
			}
		if(iSmrtSelectBusTransaction != RHTTPTransaction())
			{
			iSmrtSelectBusTransaction.Cancel();
			iSmrtSelectBusTransaction.Close();
			iSmrtSelectBusTransaction = RHTTPTransaction();
			}
		iCrowdSmrtTimeoutTimerHelper->Cancel();
		iSmrtInitalizationCycle = EFalse;
		}
	if(aQuery->iServiceTransaction != RHTTPTransaction())
		{
		aQuery->iServiceTransaction.Cancel();
		aQuery->iServiceTransaction.Close();
		aQuery->iServiceTransaction = RHTTPTransaction();
		}
	}


void CSmrtSession::CancelAllSmrtRequestsL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iSmrtCaptchaDecoderTarget.Get()) iSmrtCaptchaDecoderTarget->Cancel();
	if(iSmrtCaptchaBitmapScalerTarget.Get()) iSmrtCaptchaBitmapScalerTarget->Cancel();
	if(iSmrtSessionTransaction != RHTTPTransaction())
		{
		iSmrtSessionTransaction.Cancel();
		iSmrtSessionTransaction.Close();
		iSmrtSessionTransaction = RHTTPTransaction();
		}
	if(iCrowdSmrtSessionTransaction != RHTTPTransaction())
		{
		iCrowdSmrtSessionTransaction.Cancel();
		iCrowdSmrtSessionTransaction.Close();
		iCrowdSmrtSessionTransaction = RHTTPTransaction();
		}
	if(iCrowdSmrtSessionUpdateTransaction != RHTTPTransaction())
		{
		iCrowdSmrtSessionUpdateTransaction.Cancel();
		iCrowdSmrtSessionUpdateTransaction.Close();
		iCrowdSmrtSessionUpdateTransaction = RHTTPTransaction();
		}
	if(iSmrtCaptchaTransaction != RHTTPTransaction())
		{
		iSmrtCaptchaTransaction.Cancel();
		iSmrtCaptchaTransaction.Close();
		iSmrtCaptchaTransaction = RHTTPTransaction();
		}
	if(iSmrtSolveCaptchaTransaction != RHTTPTransaction())
		{
		iSmrtSolveCaptchaTransaction.Cancel();
		iSmrtSolveCaptchaTransaction.Close();
		iSmrtSolveCaptchaTransaction = RHTTPTransaction();
		}
	if(iSmrtSelectBusTransaction != RHTTPTransaction())
		{
		iSmrtSelectBusTransaction.Cancel();
		iSmrtSelectBusTransaction.Close();
		iSmrtSelectBusTransaction = RHTTPTransaction();
		}
	for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
		if(iSmrtQueries[i]->iServiceTransaction != RHTTPTransaction())
			{
			iSmrtQueries[i]->iServiceTransaction.Cancel();
			iSmrtQueries[i]->iServiceTransaction.Close();
			iSmrtQueries[i]->iServiceTransaction = RHTTPTransaction();
			}
	iSmrtInitalizationCycle = EFalse;
	iSmrtTimeoutTimerHelper->Cancel();
	iCrowdSmrtTimeoutTimerHelper->Cancel();
	}


TBool CSmrtSession::AllRequestsCompleted() const
{
TFunTrace funTrace(__PRETTY_FUNCTION__);

	if(iSmrtCaptchaTransaction != RHTTPTransaction()) return EFalse;
	if(iSmrtSessionTransaction != RHTTPTransaction()) return EFalse;
	if(iSmrtSolveCaptchaTransaction != RHTTPTransaction()) return EFalse;
	if(iSmrtSelectBusTransaction != RHTTPTransaction()) return EFalse;
	for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
		if(iSmrtQueries[i]->iServiceTransaction != RHTTPTransaction())
			return EFalse;
	return ETrue;
}


void CSmrtSession::MActiveHelperCallbackRunL(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer)
{
TFunTrace funTrace(__PRETTY_FUNCTION__);

if(aActiveHelper->iStatus != KErrNone) return;

	if(aActiveHelper == iCrowdSmrtTimeoutTimerHelper)
			{
			iLastFailureCrowdSmrtSession.HomeTime();
			CancelAllSmrtRequestsL();
			for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
				if( (iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending || iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPendingInitialization))
					SubmitL(iSmrtQueries[i]);
			}
	else if(aActiveHelper == iSmrtTimeoutTimerHelper)
		{
		CancelAllSmrtRequestsL();
		for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
			if( (iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending || iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPendingInitialization))
				{
				if(iSmrtQueries[i]->iTransactionType == CSmrtQuery::ESmrtConnect)
					iLastFailureSmrtConnect.HomeTime();
				SubmitL(iSmrtQueries[i]);
				}
		}

}

TInt CSmrtSession::MActiveHelperCallbackRunError(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer, TInt aError)
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
}

void CSmrtSession::MActiveHelperCallbackDoCancel(CActiveHelper<RTimer*>* aActiveHelper, RTimer* aTimer)
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	aTimer->Cancel();
}



void CSmrtSession::SubmitSmrtConnectRequestL(CSmrtQuery* aQuery)
{
TFunTrace funTrace(__PRETTY_FUNCTION__);
	TBuf8<4096> postData;
	TBuf8<128> stationNumber = *aQuery->iStationNumber;
	postData.Format(
	#include "smrt_query_post.txt"
			, &stationNumber);
	aQuery->iServiceTransactionSource->SetPostDataL(postData);
	TBuf8<1024> uristr;
	aQuery->iTransactionType = CSmrtQuery::ESmrtConnect;	
	uristr.Format(
	#include "smrt_query_url.txt"
			);
	if(aQuery->iServiceTransaction != RHTTPTransaction())
		{
		aQuery->iServiceTransaction.Cancel();
		aQuery->iServiceTransaction.Close();
		}
	delete aQuery->iServiceTransactionTarget;
	aQuery->iServiceTransactionTarget = CHTTPTransactionTarget::NewL();
	aQuery->iServiceTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedSmrtConnectAnswerL, this, aQuery, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
	aQuery->iServiceTransactionTarget->SetRunBodyData(NULL);
	aQuery->iServiceTransactionTarget->SetRunError( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::SmrtConnectTransactionError, this, aQuery, scalp::Free1, scalp::Free2) ) );			
	aQuery->iServiceTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, uristr, *aQuery->iServiceTransactionTarget, HTTP::EPOST);
	aQuery->iServiceTransaction.Request().SetBody(*aQuery->iServiceTransactionSource);	
	RHTTPRequestSetHeaderL(iHTTPSession, aQuery->iServiceTransaction.Request(), HTTP::EContentType, _L8("text/xml; charset=utf-8"));
	RHTTPRequestSetHeaderL(iHTTPSession, aQuery->iServiceTransaction.Request(), HTTP::EAcceptLanguage, _L8("en-us"));
	RHTTPRequestSetHeaderL(iHTTPSession, aQuery->iServiceTransaction.Request(), HTTP::EAccept, _L8("*/*"));
	{
	LCleanedupHandle<RStringF> fieldName ( iHTTPSession.StringPool().OpenFStringL(_L8("SOAPAction")) );
	LCleanedupHandle<RStringF> fieldValue ( iHTTPSession.StringPool().OpenFStringL(
#include "smrt_query_head.txt"
			) );
	THTTPHdrVal fieldValueVal(fieldValue.Get());
	aQuery->iServiceTransaction.Request().GetHeaderCollection().SetFieldL(
			*fieldName,
			fieldValueVal
			);
	}
	RHTTPRequestSetHeaderL(iHTTPSession, aQuery->iServiceTransaction.Request(), HTTP::EAcceptEncoding, _L8("gzip, deflate"));
	
	{
		// faster without pipelining
		RStringPool strP = iHTTPSession.StringPool();
		const TStringTable& stringTable = RHTTPSession::GetTable();
		RStringF httpPipelining = strP.StringF( HTTP::EHttpPipelining, stringTable );
		THTTPHdrVal disablePipelining = strP.StringF( HTTP::EDisablePipelining, stringTable );
		aQuery->iServiceTransaction.PropertySet().RemoveProperty( httpPipelining );
		aQuery->iServiceTransaction.PropertySet().SetPropertyL( httpPipelining, disablePipelining );
	}
	
	aQuery->iServiceTransaction.SubmitL();
	aQuery->iRequestStatus = CSmrtQuery::ERequestPending;
	(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestPending, (kFormatRequestPending()), (KNullDesC8()), (KNullDesC8()));
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtConnectTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
	iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtConnectTimeoutTimer);
}




void CSmrtSession::ReceivedSmrtConnectAnswerL(CSmrtQuery* aQuery, RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);

	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtConnectTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
	iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtConnectTimeoutTimer);
	aQuery->iServiceTransaction = RHTTPTransaction();
	iSmrtStatusCode = aTransaction.Response().StatusCode();
	if(aEvent.iStatus != THTTPEvent::ESucceeded || iSmrtStatusCode != 200)
		User::Leave(aLastError < 0 ? aLastError : KErrAbort);

	const TDesC8& requestPath = aTransaction.Request().URI().Extract(EUriPath);
	if(requestPath.Find(_L8("UserWebService.asmx")) == KErrNotFound)
		User::Leave(KErrAccessDenied);
	
		
	{
	
	TPtrC8 smrtConnectBuf;
	
	THTTPHdrVal contentEncodingHdrVal;
	TInt ret = aTransaction.Response().GetHeaderCollection().GetField(
					aTransaction.Session().StringPool().StringF(HTTP::EContentEncoding, RHTTPSession::GetTable()), 0,
					contentEncodingHdrVal
					);
	const TDesC8& contentEncoding( ret == KErrNone ? contentEncodingHdrVal.StrF().DesC() : KNullDesC8);
	if(ret == KErrNone && contentEncoding == _L8("gzip"))
		smrtConnectBuf.Set( iDeflateDecompressor->DecompressGZipL(aBuf) );
	else
		smrtConnectBuf.Set(aBuf);
	
	if(smrtConnectBuf.Find(_L8("</soap:Envelope>")) == KErrNotFound)
		User::Leave(KErrAbort);

	TInt countServices = 0;

	{
	TPtrC8 buf = smrtConnectBuf, serviceName;
	
	for(
			serviceName.Set( IrisExtractField(_L8("<Bus_Service_Number>"), _L8("</Bus_Service_Number>"), buf) ) ;
			serviceName.Length() ;
			serviceName.Set( IrisExtractField(_L8("<Bus_Service_Number>"), _L8("</Bus_Service_Number>"), buf) )
			)
		{
		++countServices;
		TPtrC8 tail1 = buf, tail2 = buf;
		TPtrC8 busStopCode = IrisExtractField(_L8("<Bus_Stop_Code>"), _L8("</Bus_Stop_Code>"), tail1);
		TPtrC8 arrival1 = IrisExtractField(_L8("<A1>"), _L8("</A1>"), tail2);
		TPtrC8 arrival2 = IrisExtractField(_L8("<A2>"), _L8("</A2>"), tail2);
		
		
		for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
			{
			TBuf8<128> queryStationNumber = *iSmrtQueries[i]->iStationNumber;
			if(		iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending &&
					iSmrtQueries[i]->iTransactionType == CSmrtQuery::ESmrtConnect &&
					queryStationNumber == busStopCode &&
					iSmrtQueries[i]->iServiceName->CompareF(serviceName) ==0
					)
				{
				iSmrtQueries[i]->iRequestStatus = CSmrtQuery::ERequestCompleted;
				(*iSmrtQueries[i]->iCallback.Get())(iSmrtQueries[i], (*iSmrtQueries[i]->iStationNumber), (*iSmrtQueries[i]->iServiceName), CSmrtQuery::ERequestCompleted, (*&kFormatRequestCompleted()), arrival1, arrival2);
				}
			}
		}
	
	if(!countServices) // most likely suggests a server problem, re-query using the old way
		User::Leave(KErrCorrupt); 
	
	for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
		{
		if(		iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending &&
				iSmrtQueries[i]->iTransactionType == CSmrtQuery::ESmrtConnect &&
				*iSmrtQueries[i]->iStationNumber == *aQuery->iStationNumber
				)
			{
			iSmrtQueries[i]->iRequestStatus = CSmrtQuery::ERequestUnavailable;
			(*iSmrtQueries[i]->iCallback.Get())(iSmrtQueries[i], (*iSmrtQueries[i]->iStationNumber), (*iSmrtQueries[i]->iServiceName), CSmrtQuery::ERequestUnavailable, (*&kFormatRequestUnavailable()), KNullDesC8(), KNullDesC8());
			}
		}
	
	}
	
	}
	
	aTransaction.Cancel();
	aTransaction.Close(); // note: if a panic is raised before reaching this line, MHFRunError will close the transaction
	}


TInt CSmrtSession::SmrtConnectTransactionError(CSmrtQuery* aQuery, TInt aError, RHTTPTransaction aTransaction)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	//REMOVED if(aTransaction != RHTTPTransaction()) aTransaction.Cancel();
	//REMOVED LCleanedupRef<RHTTPTransaction> cleanupTransaction(aTransaction);

	TInt arror = aError;
	
	iLastFailureSmrtConnect.HomeTime();
	for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
		{
		if(		iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending &&
				iSmrtQueries[i]->iTransactionType == CSmrtQuery::ESmrtConnect &&
				*iSmrtQueries[i]->iStationNumber == *aQuery->iStationNumber
				)
			{
			iSmrtQueries[i]->SubmitL();
			}
		}
	
	return KErrNone;
	
	}

void CSmrtSession::SubmitSmrtSessionCookieRequestL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iSmrtSessionTransaction != RHTTPTransaction())
		{
		iSmrtSessionTransaction.Cancel();
		iSmrtSessionTransaction.Close();
		}
	iSmrtSessionTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedSmrtSessionCookieAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
	iSmrtSessionTransactionTarget->SetRunError( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::SmrtTransactionError, this, iSmrtInitializationPilotService, scalp::Free1, scalp::Free2) ) );
	iSmrtSessionTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, _L8("http://203.126.106.149/ValidateNoHeader.aspx"), *iSmrtSessionTransactionTarget, HTTP::EGET);
	iSmrtSessionTransaction.SubmitL();
	iSmrtInitializationPilotService->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
	(*iSmrtInitializationPilotService->iCallback.Get())(iSmrtInitializationPilotService, (*iSmrtInitializationPilotService->iStationNumber), (*iSmrtInitializationPilotService->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatRequestPendingToken()), (*&KNullDesC8()), (*&KNullDesC8()));
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
	iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtTimeoutTimer);
	}





void CSmrtSession::ReceivedSmrtSessionCookieAnswerL(RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{
	
	TFunTrace funTrace(__PRETTY_FUNCTION__);

	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtSessionTransaction = RHTTPTransaction();
	iSmrtStatusCode = aTransaction.Response().StatusCode();
	if(aEvent.iStatus != THTTPEvent::ESucceeded || iSmrtStatusCode != 200)
		User::Leave(aLastError < 0 ? aLastError : KErrAbort);

	iCrowdSmrtSession = EFalse;
	{
	HBufC8* cookie = RHTTPRequestGetCookie(iHTTPSession, aTransaction.Response(), _L8("ASP.NET_SessionId"));
	if(cookie) // we do not always receive a cookie in that page (ex: if a captcha was entered wrongly, we reach this page and it does not include a cookie)
		{
		delete iSmrtSessionCookie;
		iSmrtSessionCookie = cookie;
		}
	}
	
	
	TPtrC8 buf(aBuf);
	
	{
	TPtrC8 raw = IrisExtractField(_L8("id=\"__VIEWSTATE\" value=\""), _L8("\""), buf);
	delete iSmrtViewState;
	iSmrtViewState = EscapeUtils::EscapeEncodeL(raw, EscapeUtils::EEscapeUrlEncoded);
	}
	{
	TPtrC8 raw = IrisExtractField(_L8("id=\"__EVENTVALIDATION\" value=\""), _L8("\""), buf);
	delete iSmrtEventValidation;
	iSmrtEventValidation = EscapeUtils::EscapeEncodeL(raw, EscapeUtils::EEscapeUrlEncoded);
	}
	
	
	TPtrC8 captchaUrl = IrisExtractField( _L8("<img src=\""), _L8("\" id=\"ctl00_contentMain_ImageVerifier1\""), aBuf );
	TBuf8<1024> url;
	url.Format(_L8("http://203.126.106.149/%S"), &captchaUrl, &captchaUrl);
	if(iSmrtCaptchaTransaction != RHTTPTransaction())
		{
		iSmrtCaptchaTransaction.Cancel();
		iSmrtCaptchaTransaction.Close();
		}
	iSmrtCaptchaTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedSmrtCaptchaAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
	iSmrtCaptchaTransactionTarget->SetRunError( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::SmrtTransactionError, this, iSmrtInitializationPilotService, scalp::Free1, scalp::Free2) ) );
	iSmrtCaptchaTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, url, *iSmrtCaptchaTransactionTarget, HTTP::EGET);
	if(iSmrtSessionCookie) RHTTPRequestSetCookie(iHTTPSession, iSmrtCaptchaTransaction.Request(), _L8("ASP.NET_SessionId"), *iSmrtSessionCookie);
	iSmrtCaptchaTransaction.SubmitL();
	iSmrtInitializationPilotService->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
	(*iSmrtInitializationPilotService->iCallback.Get())(iSmrtInitializationPilotService, (*iSmrtInitializationPilotService->iStationNumber), (*iSmrtInitializationPilotService->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatRequestPendingCaptcha()), (*&KNullDesC8()), (*&KNullDesC8()));
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
	iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtTimeoutTimer);
	
	aTransaction.Cancel();
	aTransaction.Close(); // note: if a panic is raised before reaching this line, MHFRunError will close the transaction
	}
void CSmrtSession::SubmitSmrtBusArrivalSearchNoHeaderRequestL(CSmrtQuery* aQuery)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	TBuf8<4096> postData;
	TBuf8<128> stationNumber = *aQuery->iStationNumber;
	aQuery->iTransactionType = CSmrtQuery::ESmrtArrivalTime;
	postData.Format(_L8("ctl00%%24scriptManager=ctl00%%24contentMain%%24upSearch%%7cctl00%%24contentMain%%24btnRefresh1&__EVENTTARGET=&__EVENTARGUMENT=&__LASTFOCUS=&__VIEWSTATE=%S&ctl00%%24contentMain%%24ddlServiceNumber=%S&ctl00%%24contentMain%%24ddlDirection=-1&ctl00%%24contentMain%%24ddlBusStop=-1&ctl00%%24contentMain%%24txtBusStop=%S&__EVENTVALIDATION=%S&ctl00%%24contentMain%%24btnRefresh1="), iSmrtViewState, aQuery->iServiceName, &stationNumber, iSmrtEventValidation);
	aQuery->iServiceTransactionSource->SetPostDataL(postData);
	if(aQuery->iServiceTransaction != RHTTPTransaction())
		{
		aQuery->iServiceTransaction.Cancel();
		aQuery->iServiceTransaction.Close();
		}
	delete aQuery->iServiceTransactionTarget;
	aQuery->iServiceTransactionTarget = CHTTPTransactionTarget::NewL();
	aQuery->iServiceTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedSmrtBusArrivalSearchNoHeaderAnswerL, this, aQuery, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
	//SetRunBodyData was used to prevent receiving the whole page but it is not useful anymore
	//aQuery->iServiceTransactionTarget->SetRunBodyData( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedSmrtBusArrivalSearchNoHeaderAnswerBodyDataL, this, aQuery, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4, scalp::Free5) ) );
	aQuery->iServiceTransactionTarget->SetRunError( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::SmrtTransactionError, this, aQuery, scalp::Free1, scalp::Free2) ) ); 
	aQuery->iServiceTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, _L8("http://203.126.106.149/BusArrivalSearchNoHeader.aspx"), *aQuery->iServiceTransactionTarget, HTTP::EPOST);
	aQuery->iServiceTransaction.Request().SetBody(*aQuery->iServiceTransactionSource);	
	if(iSmrtSessionCookie) RHTTPRequestSetCookie(iHTTPSession, aQuery->iServiceTransaction.Request(), _L8("ASP.NET_SessionId"), *iSmrtSessionCookie);
	RHTTPRequestSetHeaderL(iHTTPSession, aQuery->iServiceTransaction.Request(), HTTP::EContentType, _L8("application/x-www-form-urlencoded"));
	RHTTPRequestSetHeaderL(iHTTPSession, aQuery->iServiceTransaction.Request(), HTTP::EAcceptEncoding, _L8("gzip, deflate"));
	aQuery->iServiceTransaction.SubmitL();				
	aQuery->iRequestStatus = CSmrtQuery::ERequestPending;
	(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestPending, (*&kFormatRequestPending()), (*&KNullDesC8()), (*&KNullDesC8()));
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
	iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtTimeoutTimer);
	
	}

void CSmrtSession::ReceivedSmrtBusArrivalSearchNoHeaderAnswerBodyDataL(CSmrtQuery* aQuery, RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf, TInt aPartSize)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	_LIT8(kBeacon, "searchtime");
	const TDesC8& path = aTransaction.Request().URI().Extract(EUriPath);
	if( path.Find(_L8("BusArrivalSearchNoHeader.aspx")) != KErrNotFound && aBuf.Length() >= kBeacon().Length() + aPartSize && aBuf.Right(kBeacon().Length() + aPartSize).Find( kBeacon() ) != KErrNotFound )
		{
		THTTPEvent event = aEvent;
		event.iStatus = THTTPEvent::ESucceeded;
		ReceivedSmrtBusArrivalSearchNoHeaderAnswerL(aQuery, aTransaction, aEvent, aLastError, aBuf);
		}
	}

void CSmrtSession::ReceivedSmrtBusArrivalSearchNoHeaderAnswerL(CSmrtQuery* aQuery, RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{

	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
	iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtTimeoutTimer);

	aQuery->iServiceTransaction = RHTTPTransaction();
	iSmrtStatusCode = aTransaction.Response().StatusCode();

	{
	const TDesC8& path = aTransaction.Request().URI().Extract(EUriPath);

	if(		((path.Find(_L8("BusArrivalSearchNoHeader.aspx")) != KErrNotFound) && iSmrtStatusCode == 500)
			||
			((path.Find(_L8("ValidateNoHeader.aspx")) != KErrNotFound) && iSmrtStatusCode == 200)
		)
		{
		if(iSmrtStatusCode == 500 && (aQuery->iServiceName->Locate('R') != KErrNotFound || aQuery->iServiceName->Locate('C') != KErrNotFound) )
			{
			// not surprised that it fails, these services are not supported 
			TBuf8<64> lastErrorStr, statusCodeStr;
			lastErrorStr.Format(_L8("%d"), KErrAbort);
			statusCodeStr.Format(_L8("%d"), iSmrtStatusCode);
			aQuery->iRequestStatus = CSmrtQuery::ERequestError;
			(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestError, (*&kFormatRequestError()), (*&lastErrorStr), (*&statusCodeStr));
			}
		else if(!iSmrtInitalizationCycle) // captcha expired or we never provided any valid captcha
			{
			iSmrtInitializationPilotService = aQuery;
			iSmrtInitalizationCycle = ETrue;
			delete iSmrtSessionCookie; // we go for a brand new cookie
			iSmrtSessionCookie = NULL;
			SubmitCrowdSmrtSessionRequestL(); // try the crowd session first
			//SubmitSmrtSessionCookieRequestL();
			}
		else if(iCrowdSmrtSession && iSmrtInitializationPilotService == aQuery)
			{
			// the crowd session failed, create a brand new session
			delete iSmrtSessionCookie; // we go for a brand new cookie
			iSmrtSessionCookie = NULL;
			SubmitSmrtSessionCookieRequestL();
			}
		else
			{
			aQuery->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
			(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatRequestPendingInitialization()), (*&KNullDesC8()), (*&KNullDesC8()));
			}
		}
	else if(path.Find(_L8("BusArrivalSearchNoHeader.aspx")) != KErrNotFound && iSmrtStatusCode == 200)
		{
		
		// =========
    	_LIT8(kServicePrefix, "<tr class=\"even last\">");
    	_LIT8(kArrivalTimePrefix, "<ul class=\"legend\">");
    	
    	TPtrC8 replyBuf;
    	
    	THTTPHdrVal contentEncodingHdrVal;
    	TInt ret = aTransaction.Response().GetHeaderCollection().GetField(
    					aTransaction.Session().StringPool().StringF(HTTP::EContentEncoding, RHTTPSession::GetTable()), 0,
    					contentEncodingHdrVal
    					);
    	const TDesC8& contentEncoding( ret == KErrNone ? contentEncodingHdrVal.StrF().DesC() : KNullDesC8);
    	if(ret == KErrNone && contentEncoding == _L8("gzip"))
    		replyBuf.Set( iDeflateDecompressor->DecompressGZipL(aBuf) );
    	else
    		replyBuf.Set(aBuf);
    	
    			    	
		TPtrC8 buf = replyBuf;
			{
			
			TBool arrivalTimeFound = EFalse;
			for(;;)
				{
				TPtrC8 serviceName = *aQuery->iServiceName, nextBus, subSequentBus;
				TInt begserviceblock = buf.Find(kServicePrefix);
				if(begserviceblock != KErrNotFound)
					{
					buf.Set( buf.Mid(begserviceblock + kServicePrefix.iTypeLength) );
					serviceName.Set( IrisTrim( IrisExtractField(_L8("<td>"), _L8("</td>"), buf) ) );
					}
				TInt begnextbus = buf.Find(kArrivalTimePrefix);
				if(begnextbus != KErrNotFound)
					{
					buf.Set( buf.Mid(begnextbus + kArrivalTimePrefix.iTypeLength) );
					nextBus.Set( IrisTrim( IrisExtractField(_L8(">"), _L8("</li>"), buf) ) );
					}					
				TInt begsubsequentbus = buf.Find(kArrivalTimePrefix);
				if(begsubsequentbus != KErrNotFound)
					{
					buf.Set( buf.Mid(begsubsequentbus + kArrivalTimePrefix.iTypeLength) );
					subSequentBus.Set( IrisTrim( IrisExtractField(_L8(">"), _L8("</li>"), buf) ) );
					}
				if(nextBus.Length() || subSequentBus.Length())
					{
					arrivalTimeFound = ETrue;
					if(serviceName.CompareF(*aQuery->iServiceName) == 0)
						{
						aQuery->iRequestStatus = CSmrtQuery::ERequestCompleted;
						(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestCompleted, (*&kFormatRequestCompleted()), (*&nextBus), (*&subSequentBus));
						}
					}
				else break;
				}
			
			if(!arrivalTimeFound)
				{
				// check if there is an error
				TPtrC8 buf = replyBuf;
				TPtrC8 errorMessageBlock = IrisExtractField(_L8("<div id=\"ctl00_contentMain_divMessage\""), _L8("/div>"), buf);
				if(errorMessageBlock.Length())
					{
					TPtrC8 errorMessage = IrisTrim( IrisExtractField(_L8(">"), _L8("<"), errorMessageBlock ) );
					if(errorMessage.Length())
						{
						aQuery->iRequestStatus = CSmrtQuery::ERequestCompleted;
						(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestCompleted, (*&kFormatRequestCompleted()), (*&errorMessage), (*&errorMessage));
						}
					}
				}
			
			}
		
		// =========
		if(iSmrtInitalizationCycle && aQuery == iSmrtInitializationPilotService)
			{
			iSmrtInitalizationCycle = EFalse;
			for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
				if(iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPendingInitialization)
					SubmitL(iSmrtQueries[i]);
			}		
		
		if(AllRequestsCompleted())
			{
			for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
				if(iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending)
					{
					iSmrtQueries[i]->iRequestStatus = CSmrtQuery::ERequestUnavailable;
					(*iSmrtQueries[i]->iCallback.Get())(iSmrtQueries[i], (*iSmrtQueries[i]->iStationNumber), (*iSmrtQueries[i]->iServiceName), CSmrtQuery::ERequestUnavailable, (*&kFormatRequestUnavailable()), (*&KNullDesC8()), (*&KNullDesC8()));	
					}
			}
		
		}
	else
		User::Leave(aLastError < 0 ? aLastError : KErrAbort);
	}
	
	aTransaction.Cancel();
	aTransaction.Close(); // note: if a panic is raised before reaching this line, MHFRunError will close the transaction
	
	
	}

void CSmrtSession::ReceivedSmrtCaptchaAnswerL(RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtCaptchaTransaction = RHTTPTransaction();
	iSmrtStatusCode = aTransaction.Response().StatusCode();
	if(aEvent.iStatus != THTTPEvent::ESucceeded || iSmrtStatusCode != 200)
		User::Leave(aLastError < 0 ? aLastError : KErrAbort);

	
	if(iSmrtCaptchaDecoderTarget.Get()) iSmrtCaptchaDecoderTarget->Cancel();
	iSmrtCaptchaDecoder = CImageDecoder::DataNewL(CCoeEnv::Static()->FsSession(), iSmrtCaptchaTransactionTarget->Body()); // a bit dangerous...
	iSmrtCaptchaBitmap = new(ELeave)CFbsBitmap(); 
	iSmrtCaptchaBitmap->Create(iSmrtCaptchaDecoder->FrameInfo(0).iOverallSizeInPixels,iSmrtCaptchaDecoder->FrameInfo(0).iFrameDisplayMode);		
	iSmrtCaptchaDecoderTarget = new (ELeave) scalp::CActiveTarget(
			scalp::MakeFunctionL ( scalp::Bind(&CImageDecoder::Cancel, iSmrtCaptchaDecoder.Get()) ),
			scalp::MakeFunctionL ( scalp::Bind(&CSmrtSession::SmrtTransactionError, this, iSmrtInitializationPilotService, scalp::Free1, RHTTPTransaction()) )
			);
	iSmrtCaptchaDecoderTarget->AppendRunL(
			scalp::MakeFunctionL ( scalp::Bind(&CSmrtSession::SmrtCaptchaImageDecoded, this) )
	);
	iSmrtCaptchaDecoder->Convert(&iSmrtCaptchaDecoderTarget->iStatus, *iSmrtCaptchaBitmap);
	iSmrtCaptchaDecoderTarget->SetActive();
	iSmrtInitializationPilotService->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
	(*iSmrtInitializationPilotService->iCallback.Get())(iSmrtInitializationPilotService, (*iSmrtInitializationPilotService->iStationNumber), (*iSmrtInitializationPilotService->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatSolvingCaptcha()), (*&KNullDesC8()), (*&KNullDesC8()));
	
	aTransaction.Cancel();
	aTransaction.Close(); // note: if a panic is raised before reaching this line, MHFRunError will close the transaction
	}
TInt CSmrtSession::SmrtTransactionError(CSmrtQuery* aQuery, TInt aError, RHTTPTransaction aTransaction)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	//REMOVED if(aTransaction != RHTTPTransaction()) aTransaction.Cancel();
	//REMOVED LCleanedupRef<RHTTPTransaction> cleanupTransaction(aTransaction);
	TBuf8<64> lastErrorStr, statusCodeStr;
	lastErrorStr.Format(_L8("%d"), aError);
	statusCodeStr.Format(_L8("%d"), iSmrtStatusCode);
	
	if(iSmrtInitalizationCycle)
		{
		iSmrtInitalizationCycle = EFalse;
		for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
			{
			CSmrtQuery* query = iSmrtQueries[i];
			if(iSmrtQueries[i]->iTransactionType == CSmrtQuery::ESmrtArrivalTime && ( iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPending || iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPendingInitialization ) ) 
				{
				iSmrtQueries[i]->iRequestStatus = CSmrtQuery::ERequestError;
				(*iSmrtQueries[i]->iCallback.Get())(iSmrtQueries[i], (*iSmrtQueries[i]->iStationNumber), (*iSmrtQueries[i]->iServiceName), CSmrtQuery::ERequestError, (*&kFormatRequestError()), (*&lastErrorStr), (*&statusCodeStr));
				}
			}
		}
	else
		{
		aQuery->iRequestStatus = CSmrtQuery::ERequestError;
		(*aQuery->iCallback.Get())(aQuery, (*aQuery->iStationNumber), (*aQuery->iServiceName), CSmrtQuery::ERequestError, (*&kFormatRequestError()), (*&lastErrorStr), (*&statusCodeStr));
		}

	return KErrNone;
	
	}
void CSmrtSession::SmrtCaptchaImageDecoded()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if(iSmrtCaptchaDecoderTarget->iStatus == KErrNone)
		{
		if(iSmrtCaptchaBitmapScalerTarget.Get()) iSmrtCaptchaBitmapScalerTarget->Cancel();
		iSmrtCaptchaBitmapScaler = CBitmapScaler::NewL();
		iSmrtCaptchaBitmapScalerTarget = new (ELeave) scalp::CActiveTarget (
				scalp::MakeFunctionL ( scalp::Bind(&CBitmapScaler::Cancel, iSmrtCaptchaBitmapScaler.Get()) ),
				scalp::MakeFunctionL ( scalp::Bind(&CSmrtSession::SmrtTransactionError, this, iSmrtInitializationPilotService, scalp::Free1, RHTTPTransaction()) )
				);
		TSize screenSize = CEikonEnv::Static()->ScreenDevice()->SizeInPixels();
		iSmrtCaptchaBitmapScaler->Scale(&iSmrtCaptchaBitmapScalerTarget->iStatus, *iSmrtCaptchaBitmap,
				TSize(
						screenSize.iWidth/2,
						screenSize.iHeight/2
						)
				);
		iSmrtCaptchaBitmapScalerTarget->AppendRunL(
				scalp::MakeFunctionL ( scalp::Bind(&CSmrtSession::SmrtCaptchaImageScaled, this) )
		);
		iSmrtCaptchaBitmapScalerTarget->SetActive();
		}
	else if(iSmrtCaptchaDecoderTarget->iStatus != KErrCancel)
		User::Leave(iSmrtCaptchaDecoderTarget->iStatus.Int());
	
	}

#define KAknSplitInputEnabled   0x2001E2C0
#define KAknSplitInputDisabled  0x2001E2C1
struct CSmrtCaptchaDialog : public CAknDialog
	{
	TInt& iCaptcha;
	TBool iAknSplitInputEnabled;
	CSmrtCaptchaDialog(TInt& aCaptcha) : iCaptcha(aCaptcha), iAknSplitInputEnabled(EFalse) {}
    virtual TBool OkToExitL(TInt aButtonId)
    	{
    	TFunTrace funTrace(__PRETTY_FUNCTION__);
    	CAknQueryControl* control = static_cast<CAknQueryControl*>(Control(2));
    	CAknIntegerEdwin* captchaEditor = (CAknIntegerEdwin*)control->ControlByLayoutOrNull(ENumberLayout);
    	captchaEditor->GetTextAsInteger(iCaptcha);
    	return CEikDialog::OkToExitL(aButtonId);
    	}
    virtual void SetSizeAndPosition(const TSize& aSize)
    	{
    	CAknDialog::SetSizeAndPosition(aSize);
    	
    	if(iAknSplitInputEnabled)
    		{
			if(1 == 1)
				{
				SetPosition(
						TPoint(
								Position().iX,0
								)
							);
				}
			else
				{
				CAknQueryControl* control = static_cast<CAknQueryControl*>(Control(2));
				CAknIntegerEdwin* captchaEditor = (CAknIntegerEdwin*)control->ControlByLayoutOrNull(ENumberLayout);
				if( captchaEditor->PositionRelativeToScreen().iY + captchaEditor->Rect().Height() > CEikonEnv::Static()->EikAppUi()->ClientRect().Height() ) // split screen
					{
					SetPosition( Position() -
							TPoint(
									0,
									captchaEditor->PositionRelativeToScreen().iY + captchaEditor->Rect().Height() - CEikonEnv::Static()->EikAppUi()->ClientRect().Height() 
									)
								);
					}
				}
    		}
    	}
    virtual void HandleResourceChange(TInt aType)
    	{
    	TFunTrace funTrace(__PRETTY_FUNCTION__);
    	if ( aType == KAknSplitInputEnabled )
    		iAknSplitInputEnabled = ETrue;
    	else if ( aType == KAknSplitInputDisabled )
    		iAknSplitInputEnabled = EFalse;
    	CAknDialog::HandleResourceChange(aType);
    	}
    
	};


struct CSmrtCaptchaDialog2 : public CAknNumberQueryDialog
	{
	CSmrtCaptchaDialog2(TInt& aNumber, const TTone& aTone) : CAknNumberQueryDialog(aNumber, aTone) { }
	virtual void SetSizeAndPosition(const TSize& aSize)
		{
		/*
		CAknNumberQueryDialog::SetSizeAndPosition(aSize);
		CEikImage* captchaImage = (CEikImage*)Control(1);
		SetSize(aSize);
		TRect clientRect = CEikonEnv::Static()->EikAppUi()->ClientRect();
		SetPosition( TPoint(Position().iX, Max(0, (clientRect.Height() - Size().iHeight)/2)) );
		*/
		CAknDialog::SetSizeAndPosition( aSize );
		TRect cRect = ((CAknAppUi*)CCoeEnv::Static()->AppUi())->ClientRect();
		TRect rect = Rect();
		//SetExtent(TPoint(Position().iX, cRect.iBr.iY - rect.Height()), rect.Size());
		}
	};


void CSmrtSession::SmrtCaptchaImageScaled()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	
	if(iSmrtCaptchaBitmapScalerTarget->iStatus == KErrNone)
		{
		
		TInt button;
		{
		iSmrtCaptcha = 0;
		CAknNumberQueryDialog* captchaDialog = new (ELeave) CSmrtCaptchaDialog2(iSmrtCaptcha,CAknQueryDialog::ENoTone);
		captchaDialog->PrepareLC(R_CAPTCHA_DIALOG);
		captchaDialog->SetPromptL(_L("Please solve the Captcha requested by SMRT:"));		
		CEikImage* captchaImage = (CEikImage*)captchaDialog->Control(1);
		//captchaImage->SetSize(iSmrtCaptchaBitmap->SizeInPixels());
		//captchaDialog->SetSize( /*captchaDialog->Size() +*/ TSize(0, captchaImage->Size().iHeight) );
		delete captchaImage->Bitmap();
		captchaImage->SetBitmap(iSmrtCaptchaBitmap.Unmanage());
		iSmrtCaptchaDialog = captchaDialog;
		button = captchaDialog->RunLD();
		iSmrtCaptchaDialog = NULL;
		}

		
		if(button == EAknSoftkeyOk)
		{
			if(iSmrtSolveCaptchaTransaction != RHTTPTransaction())
				{
				iSmrtSolveCaptchaTransaction.Cancel();
				iSmrtSolveCaptchaTransaction.Close();
				}
			iSmrtSolveCaptchaTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedSmrtSolveCaptchaAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
			iSmrtSolveCaptchaTransactionTarget->SetRunError( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::SmrtTransactionError, this, iSmrtInitializationPilotService, scalp::Free1, scalp::Free2) ) );
			iSmrtSolveCaptchaTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, _L8("http://203.126.106.149/ValidateNoHeader.aspx"), *iSmrtSolveCaptchaTransactionTarget, HTTP::EPOST);
			if(iSmrtSessionCookie) RHTTPRequestSetCookie(iHTTPSession, iSmrtSolveCaptchaTransaction.Request(), _L8("ASP.NET_SessionId"), *iSmrtSessionCookie);
			RHTTPRequestSetHeaderL(iHTTPSession, iSmrtSolveCaptchaTransaction.Request(), HTTP::EContentType, _L8("application/x-www-form-urlencoded"));
			iSmrtSolveCaptchaTransaction.Request().SetBody(*iSmrtCaptchaTransactionSource);
			TBuf8<4096> postData;
			postData.Format(_L8("__LASTFOCUS=&__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%S&ctl00%%24contentMain%%24txtValidate=%0*d&ctl00%%24contentMain%%24Submit=%%C2%%A0&__EVENTVALIDATION=%S"), iSmrtViewState, 3, iSmrtCaptcha, iSmrtEventValidation);
			iSmrtCaptchaTransactionSource->SetPostDataL(postData);
			iSmrtSolveCaptchaTransaction.SubmitL();
			iSmrtTimeoutTimerHelper->Cancel();
			iSmrtTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
			iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtTimeoutTimer);
			iSmrtInitializationPilotService->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
			(*iSmrtInitializationPilotService->iCallback.Get())(iSmrtInitializationPilotService, (*iSmrtInitializationPilotService->iStationNumber), (*iSmrtInitializationPilotService->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatRequestSubmittingCaptcha()), (*&KNullDesC8()), (*&KNullDesC8()));
		}
		else
			{
			//delete iSmrtSessionCookie;
			//iSmrtSessionCookie = NULL; // we have to explicitely start from a new cookie because the existing cookie will always return 500 error when we query arrival times (no redirection to validation page)
			User::Leave(KErrCancel);
			}
	}
	else if(iSmrtCaptchaBitmapScalerTarget->iStatus != KErrCancel)
		User::Leave(iSmrtCaptchaBitmapScalerTarget->iStatus.Int());
	
	}

void CSmrtSession::ReceivedSmrtSolveCaptchaAnswerL(RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtSolveCaptchaTransaction = RHTTPTransaction();
	iSmrtStatusCode = aTransaction.Response().StatusCode();
	if(aEvent.iStatus != THTTPEvent::ESucceeded || iSmrtStatusCode != 200)
		User::Leave(aLastError < 0 ? aLastError : KErrAbort);

	const TDesC8& path = aTransaction.Request().URI().Extract(EUriPath);
	if(path.Find(_L8("ValidateNoHeader.aspx")) != KErrNotFound)
		{
		return ReceivedSmrtSessionCookieAnswerL(aTransaction, aEvent, aLastError, aBuf);
		}
	else if(path.Find(_L8("BusArrivalSearchNoHeader.aspx")) != KErrNotFound)
		{
		
		
		TPtrC8 buf(aBuf);
		{
		TPtrC8 raw = IrisExtractField(_L8("id=\"__VIEWSTATE\" value=\""), _L8("\""), buf);
		delete iSmrtViewState;
		iSmrtViewState = EscapeUtils::EscapeEncodeL(raw, EscapeUtils::EEscapeUrlEncoded);
		}
		{
		TPtrC8 raw = IrisExtractField(_L8("id=\"__EVENTVALIDATION\" value=\""), _L8("\""), buf);
		delete iSmrtEventValidation;
		iSmrtEventValidation = EscapeUtils::EscapeEncodeL(raw, EscapeUtils::EEscapeUrlEncoded);
		}
		
		if(iSmrtSelectBusTransaction != RHTTPTransaction())
			{
			iSmrtSelectBusTransaction.Cancel();
			iSmrtSelectBusTransaction.Close();
			}
		iSmrtSelectBusTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedSmrtSelectBusAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
		iSmrtSelectBusTransactionTarget->SetRunError( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::SmrtTransactionError, this, iSmrtInitializationPilotService, scalp::Free1, scalp::Free2) ) );
		iSmrtSelectBusTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, _L8("http://203.126.106.149/BusArrivalSearchNoHeader.aspx"), *iSmrtSelectBusTransactionTarget, HTTP::EPOST);
		if(iSmrtSessionCookie) RHTTPRequestSetCookie(iHTTPSession, iSmrtSelectBusTransaction.Request(), _L8("ASP.NET_SessionId"), *iSmrtSessionCookie);
		RHTTPRequestSetHeaderL(iHTTPSession, iSmrtSelectBusTransaction.Request(), HTTP::EContentType, _L8("application/x-www-form-urlencoded"));
		iSmrtSelectBusTransaction.Request().SetBody(*iSmrtSelectBusTransactionSource);
		TBuf8<4096> postData;
		postData.Format(_L8("ctl00%%24scriptManager=ctl00%%24contentMain%%24upSearch%%7Cctl00%%24contentMain%%24ddlServiceNumber&__EVENTTARGET=ctl00%%24contentMain%%24ddlServiceNumber&__EVENTARGUMENT=&__LASTFOCUS=&__VIEWSTATE=%S&ctl00%%24contentMain%%24ddlServiceNumber=188&ctl00%%24contentMain%%24ddlDirection=Select&ctl00%%24contentMain%%24ddlBusStop=Select&ctl00%%24contentMain%%24txtBusStop=&__EVENTVALIDATION=%S&"), iSmrtViewState, iSmrtEventValidation);
		iSmrtSelectBusTransactionSource->SetPostDataL(postData);
		iSmrtSelectBusTransaction.SubmitL();
		iSmrtTimeoutTimerHelper->Cancel();
		iSmrtTimeoutTimer.After(iSmrtTimeoutTimerHelper->iStatus, kSmrtTimeout);
		iSmrtTimeoutTimerHelper->SetActive(this, &iSmrtTimeoutTimer);
		iSmrtInitializationPilotService->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
		(*iSmrtInitializationPilotService->iCallback.Get())(iSmrtInitializationPilotService, (*iSmrtInitializationPilotService->iStationNumber), (*iSmrtInitializationPilotService->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatRequestSelectingBus()), (*&KNullDesC8()), (*&KNullDesC8()));
		
		
		}
	
	aTransaction.Cancel();
	aTransaction.Close(); // note: if a panic is raised before reaching this line, MHFRunError will close the transaction
	
	}

void CSmrtSession::ReceivedSmrtSelectBusAnswerL(RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iSmrtTimeoutTimerHelper->Cancel();
	iSmrtSelectBusTransaction = RHTTPTransaction();
	iSmrtStatusCode = aTransaction.Response().StatusCode();
	if(aEvent.iStatus != THTTPEvent::ESucceeded || iSmrtStatusCode != 200)
		User::Leave(aLastError < 0 ? aLastError : KErrAbort);

	const TDesC8& path = aTransaction.Request().URI().Extract(EUriPath);
	if(path.Find(_L8("ValidateNoHeader.aspx")) != KErrNotFound)
		{
		// this should never happen, our captcha is good and we only selected one bus
		return ReceivedSmrtSessionCookieAnswerL(aTransaction, aEvent, aLastError, aBuf);
		}
	else if(path.Find(_L8("BusArrivalSearchNoHeader.aspx")) != KErrNotFound)
		{
		iSmrtInitalizationCycle = EFalse;

		TPtrC8 buf(aBuf);
		{
		TPtrC8 raw = IrisExtractField(_L8("id=\"__VIEWSTATE\" value=\""), _L8("\""), buf);
		delete iSmrtViewState;
		iSmrtViewState = EscapeUtils::EscapeEncodeL(raw, EscapeUtils::EEscapeUrlEncoded);
		}
		{
		TPtrC8 raw = IrisExtractField(_L8("id=\"__EVENTVALIDATION\" value=\""), _L8("\""), buf);
		delete iSmrtEventValidation;
		iSmrtEventValidation = EscapeUtils::EscapeEncodeL(raw, EscapeUtils::EEscapeUrlEncoded);
		}
		
		
		for(TInt i = 0 ; i < iSmrtQueries.Count() ; ++i)
			if(iSmrtQueries[i]->iRequestStatus == CSmrtQuery::ERequestPendingInitialization)
				SubmitL(iSmrtQueries[i]);
		
		SubmitCrowdSmrtSessionUpdateRequestL();
		}
	
	aTransaction.Cancel();
	aTransaction.Close(); // note: if a panic is raised before reaching this line, MHFRunError will close the transaction
	}


void CSmrtSession::SubmitCrowdSmrtSessionRequestL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	TBuf8<1024> url;
	url.Format(_L8("http://singapore-bus.appspot.com/getSmrtSession?id=%d"), iCrowdSmrtSessionId);
	if(iCrowdSmrtSessionTransaction != RHTTPTransaction())
		{
		iCrowdSmrtSessionTransaction.Cancel();
		iCrowdSmrtSessionTransaction.Close();
		}
	iCrowdSmrtSessionTransactionTarget->SetRun( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::ReceivedCrowdSmrtSessionAnswerL, this, scalp::Free1, scalp::Free2, scalp::Free3, scalp::Free4) ) );
	iCrowdSmrtSessionTransactionTarget->SetRunError( scalp::MakeFunctionL( scalp::Bind(&CSmrtSession::CrowdSmrtTransactionError, this, iSmrtInitializationPilotService, scalp::Free1, scalp::Free2) ) );
	iCrowdSmrtSessionTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, url, *iCrowdSmrtSessionTransactionTarget, HTTP::EGET);
	iCrowdSmrtSessionTransaction.SubmitL();
	iCrowdSmrtSession = ETrue;
	iSmrtInitializationPilotService->iRequestStatus = CSmrtQuery::ERequestPendingInitialization;
	iSmrtInitializationPilotService->iTransactionType = CSmrtQuery::ESmrtArrivalTime;
	(*iSmrtInitializationPilotService->iCallback.Get())(iSmrtInitializationPilotService, (*iSmrtInitializationPilotService->iStationNumber), (*iSmrtInitializationPilotService->iServiceName), CSmrtQuery::ERequestPendingInitialization, (*&kFormatRequestPendingCrowdToken()), (*&KNullDesC8()), (*&KNullDesC8()));
	iCrowdSmrtTimeoutTimerHelper->Cancel();
	iCrowdSmrtTimeoutTimer.After(iCrowdSmrtTimeoutTimerHelper->iStatus, kCrowdSmrtTimeout);
	iCrowdSmrtTimeoutTimerHelper->SetActive(this, &iCrowdSmrtTimeoutTimer);	
	}
void CSmrtSession::ReceivedCrowdSmrtSessionAnswerL(RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);

	iCrowdSmrtTimeoutTimerHelper->Cancel();
	iCrowdSmrtSessionTransaction = RHTTPTransaction();
	iSmrtStatusCode = aTransaction.Response().StatusCode();
	if(aEvent.iStatus != THTTPEvent::ESucceeded || iSmrtStatusCode != 200)
		User::Leave(aLastError < 0 ? aLastError : KErrAbort);

	TPtrC8 buf(aBuf);
	{
	TInt sepLoc = buf.Locate(' ');
	if(sepLoc == KErrNotFound) User::Leave(KErrNotFound);
	if(sepLoc == 0) User::Leave(KErrNotFound);
	if(sepLoc == buf.Length()-1) User::Leave(KErrNotFound);
	delete iSmrtSessionCookie;
	iSmrtSessionCookie = buf.Left(sepLoc).AllocL();
	buf.Set( buf.Mid(sepLoc + 1) );
	}
	
	{
	TInt sepLoc = buf.Locate(' ');
	if(sepLoc == KErrNotFound) User::Leave(KErrNotFound);
	if(sepLoc == 0) User::Leave(KErrNotFound);
	if(sepLoc == buf.Length()-1) User::Leave(KErrNotFound);
	delete iSmrtViewState;
	iSmrtViewState = buf.Left(sepLoc).AllocL();
	buf.Set( buf.Mid(sepLoc + 1) );
	}

	{
	delete iSmrtEventValidation;
	iSmrtEventValidation = buf.AllocL();
	}
	
	SubmitSmrtBusArrivalSearchNoHeaderRequestL(iSmrtInitializationPilotService);
	aTransaction.Cancel();
	aTransaction.Close(); // note: if a panic is raised before reaching this line, MHFRunError will close the transaction	
	}
void CSmrtSession::SubmitCrowdSmrtSessionUpdateRequestL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	TBuf8<128> url;
	url.Format(_L8("http://singapore-bus.appspot.com/setSmrtSession?id=%d"), iCrowdSmrtSessionId);
	TBuf8<8192> postData;
	postData.Format(_L8("cookie=%S&viewState=%S&eventValidation=%S"), iSmrtSessionCookie, iSmrtViewState, iSmrtEventValidation);
	if(iCrowdSmrtSessionUpdateTransaction != RHTTPTransaction())
		{
		iCrowdSmrtSessionUpdateTransaction.Cancel();
		iCrowdSmrtSessionUpdateTransaction.Close();
		}
	iCrowdSmrtSessionUpdateTransaction = RHTTPSessionOpenTransactionL(iHTTPSession, url, *iCrowdSmrtSessionUpdateTransactionTarget, HTTP::EPOST);
	RHTTPRequestSetHeaderL(iHTTPSession, iCrowdSmrtSessionUpdateTransaction.Request(), HTTP::EContentType, _L8("application/x-www-form-urlencoded"));
	iCrowdSmrtSessionUpdateTransaction.Request().SetBody(*iCrowdSmrtSessionUpdateTransactionSource);
	iCrowdSmrtSessionUpdateTransactionSource->SetPostDataL(postData);
	iCrowdSmrtSessionUpdateTransaction.SubmitL();	
	}
void CSmrtSession::ReceivedCrowdSmrtSessionUpdateAnswerL(RHTTPTransaction aTransaction, THTTPEvent aEvent, TInt aLastError, TPtrC8 aBuf)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iCrowdSmrtSessionUpdateTransaction = RHTTPTransaction();
	aTransaction.Cancel();
	aTransaction.Close();	
	}
TInt CSmrtSession::CrowdSmrtTransactionError(CSmrtQuery* aQuery, TInt aError, RHTTPTransaction aTransaction)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	//REMOVED aTransaction.Cancel();
	//REMOVED LCleanedupRef<RHTTPTransaction> cleanupTransaction(aTransaction);
	
	SubmitSmrtSessionCookieRequestL();

	return KErrNone;
	}


CSmrtQuery::CSmrtQuery(CSmrtSession* aSession, const TDesC8& aServiceName, const TDesC8& aStationNumber, TCallback* aCallback)
: iSession(aSession), iServiceName(NULL), iStationNumber(NULL), iCallback(aCallback)
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iServiceName = aServiceName.AllocLC();
	iStationNumber = aStationNumber.AllocLC();
	CleanupStack::Pop(2);
	iServiceTransactionSource = new (ELeave) CHTTPTransactionSource;
	iSession->iSmrtQueries.AppendL(this);
	}

void CSmrtQuery::SubmitL()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iSession->SubmitL(this);
	}
void CSmrtQuery::Cancel()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	iSession->Cancel(this);
	}

CSmrtQuery::~CSmrtQuery()
	{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	TRAPD(err, Cancel()); // ignore leaves
	delete iServiceName;
	delete iStationNumber;
	delete iServiceTransactionTarget;
	delete iServiceTransactionSource;
	TInt i;
	for(i = 0 ; i < iSession->iSmrtQueries.Count() && iSession->iSmrtQueries[i] != this ; ++i);
	if(i < iSession->iSmrtQueries.Count())
		iSession->iSmrtQueries.Remove(i);
	}


